package com.vren.addressParse.modules.addressParse;

import com.alibaba.excel.EasyExcel;
import com.vren.addressParse.common.listener.ExcelListener;
import com.vren.addressParse.common.utils.MyThreadFactory;
import com.vren.addressParse.modules.addressParse.domain.address.Address;
import com.vren.addressParse.modules.addressParse.domain.dto.AddressDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ClassName:ParseService
 * @Description:
 * @Author: vren
 * @Date: 2022/6/24 17:53
 */
@Service
@Slf4j
public class ParseService {

    public static final int batchSize = 200;
    @Autowired
    private AddressParseService addressParseService;

    private final ExecutorService executorService = Executors.newFixedThreadPool(50, MyThreadFactory.create("address-parse"));


    public Address parse(AddressDTO dto) {
        log.info("解析数据：{}", dto.getAddress());
        Address parse = addressParseService.parse(dto.getAddress());
        parse.setKeyId(dto.getKeyId());
        return parse;
    }

    public List<Address> batch(List<AddressDTO> list) {
        log.info("解析条数{}", list.size());
        List<List<AddressDTO>> partition = ListUtils.partition(list, batchSize);
        List<Address> result = new ArrayList<>();
        List<CompletableFuture<List<Address>>> futures = new ArrayList<>();
        for (List<AddressDTO> dtos : partition) {
            futures.add(parseCompletableFuture(dtos, result));
        }
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        return result;
    }

    public List<Address> analysisExcel(MultipartFile excel) {
        List<Address> result = null;
        try {
            ExcelListener excelListener = new ExcelListener(this);
            EasyExcel.read(excel.getInputStream(), AddressDTO.class, excelListener).sheet().doRead();
            result = excelListener.getResult();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public CompletableFuture<List<Address>> parseCompletableFuture(List<AddressDTO> dtos, List<Address> result) {
        return CompletableFuture.supplyAsync(() -> {
            List<Address> addresses = new ArrayList<>();
            log.info(Thread.currentThread().getName());
            for (AddressDTO dto : dtos) {
                Address parse = parse(dto);
                parse.setKeyId(dto.getKeyId());
                addresses.add(parse);
            }
            return addresses;
        }, executorService).whenComplete((r, e) -> result.addAll(r));
    }


}
